package org.demo.test.socket.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.AttributeKey;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.DefaultThreadFactory;

import java.nio.channels.spi.SelectorProvider;
import java.util.concurrent.ThreadFactory;

import org.apache.log4j.Logger;

public class NettyHttpServer {

	public static void main(String[] args) {
		try {
			// 主服务启动器
			ServerBootstrap serverBootstrap = new ServerBootstrap();
			// boss线程池
			EventLoopGroup bossLoopGroup = new NioEventLoopGroup(1);

			// work线程池
			ThreadFactory threadFactory = new DefaultThreadFactory(
					"Work thread pool");
			int processorNum = Runtime.getRuntime().availableProcessors();
			EventLoopGroup workLoopGroup = new NioEventLoopGroup(
					processorNum * 2, threadFactory,
					SelectorProvider.provider());
			//
			serverBootstrap.group(bossLoopGroup, workLoopGroup);

			// 设置服务的通道类型
			serverBootstrap.channel(NioServerSocketChannel.class);
			serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
				@Override
				protected void initChannel(NioSocketChannel ch) throws Exception {
					ch.pipeline().addLast(new HttpResponseEncoder());
					ch.pipeline().addLast(new HttpRequestDecoder());
					ch.pipeline().addLast(new HttpServerHandler());
				}
			});

			// 设置服务器绑定的端口IP
			serverBootstrap.option(ChannelOption.SO_BACKLOG, 128);
			serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
			//坑爹的6666端口，在Google浏览器下是属于默认非安全端口列表中的一个
			//serverBootstrap.bind("0.0.0.0", 6666);
			serverBootstrap.bind("0.0.0.0", 80);
			/*ChannelFuture cf = serverBootstrap.bind("0.0.0.0", 16666).sync();
			cf.channel().closeFuture().sync();*/
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			
		}
	}
}

class HttpServerHandler extends ChannelInboundHandlerAdapter {

	Logger logger = Logger.getLogger(HttpServerHandler.class);

	private static AttributeKey<StringBuffer> content = AttributeKey
			.valueOf("content");

	@Override
	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
		logger.info("channelRegistered 注册!");
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		logger.info("channelRegistered 激活!");
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		// TODO Auto-generated method stub
		super.channelInactive(ctx);
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		if(msg instanceof HttpRequest){
			logger.info("处理：HttpRequest");
			HttpRequest request = (HttpRequest)msg;
			logger.info("method="+request.method().name()+" URI="+request.uri());
		}
		if(msg instanceof HttpContent){
			logger.info("处理：HttpContent");
			HttpContent content = (HttpContent)msg;
			ByteBuf bb = content.content();
			String str = bb.toString(CharsetUtil.UTF_8);
			logger.info(str);
		}
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		// TODO Auto-generated method stub
		logger.info("接收数据完毕 !");
		String returnVal = "处理完毕!";
		FullHttpResponse fhr = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
		fhr.headers().set(HttpHeaderNames.CONTENT_LENGTH,returnVal.length());
		ByteBuf res = fhr.content();
		res.writeBytes(returnVal.getBytes("UTF-8"));
		ctx.writeAndFlush(fhr);
	}

}
